package br.com.gscorp.bankLion.init;

import java.beans.PropertyVetoException;
import java.util.Properties;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.flywaydb.core.Flyway;
import org.hibernate.ejb.HibernatePersistence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:bankLion.properties")
@EnableJpaRepositories("br.com.gscorp.bankLion.repository")
@EnableScheduling
public class SpringConfig {

	@Resource
	private Environment env;

	@Bean(initMethod="migrate")
	public Flyway flyway(DataSource dataSource){
		Flyway flyway = new Flyway();
		flyway.setInitVersion("1.0.0.1");
		flyway.setInitOnMigrate(true);
		flyway.setSchemas("dne");
		flyway.setDataSource(dataSource);
		flyway.setEncoding("UTF-8");
		flyway.setLocations("/db/migration");
		return flyway;
	}

	@Bean
	public DataSource dataSource() throws IllegalStateException, PropertyVetoException {
		ComboPooledDataSource dataSource = new ComboPooledDataSource();

		dataSource.setDriverClass(env
				.getRequiredProperty(PropertyConstants.PROPERTY_NAME_DATABASE_DRIVER).trim());
		dataSource.setJdbcUrl(env.getRequiredProperty(PropertyConstants.PROPERTY_NAME_DATABASE_URL).trim());
		dataSource.setUser(env
				.getRequiredProperty(PropertyConstants.PROPERTY_NAME_DATABASE_USERNAME));
		dataSource.setPassword(env
				.getRequiredProperty(PropertyConstants.PROPERTY_NAME_DATABASE_PASSWORD));
		dataSource.setMaxStatements(500);
		dataSource.setMaxIdleTime(1800);
		dataSource.setMaxPoolSize(50);
		dataSource.setMinPoolSize(2);
		dataSource.setInitialPoolSize(2);
		dataSource.setAcquireIncrement(3);
		dataSource.setIdleConnectionTestPeriod(3000);
		return dataSource;
	}

	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws IllegalStateException, PropertyVetoException {
		LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
		entityManagerFactoryBean.setDataSource(dataSource());
		entityManagerFactoryBean
		.setPersistenceProviderClass(HibernatePersistence.class);
		entityManagerFactoryBean
		.setPackagesToScan(env
				.getRequiredProperty(PropertyConstants.PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));

		entityManagerFactoryBean.setJpaProperties(hibProperties());

		return entityManagerFactoryBean;
	}

	private Properties hibProperties() {
		Properties properties = new Properties();
		properties.put(PropertyConstants.PROPERTY_NAME_HIBERNATE_DIALECT,
				env.getRequiredProperty(PropertyConstants.PROPERTY_NAME_HIBERNATE_DIALECT));
		properties.put(PropertyConstants.PROPERTY_NAME_HIBERNATE_SHOW_SQL,
				env.getRequiredProperty(PropertyConstants.PROPERTY_NAME_HIBERNATE_SHOW_SQL));
		properties.put(PropertyConstants.PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO,
				env.getRequiredProperty(PropertyConstants.PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO));
		properties.put(PropertyConstants.PROPERTY_JODA_TIMA_TYPE, "true");
		return properties;
	}

	@Bean
	public JpaTransactionManager transactionManager() throws IllegalStateException, PropertyVetoException {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(entityManagerFactory()
				.getObject());
		return transactionManager;
	}
}
